package config

import (
	"strings"

	"github.com/glennliao/apijson-go/consts"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/util/gconv"
)

type Q请求配置 struct {
	T调试等级 int8
	B版本号  string
	Q请求方法 string
	B标签   string
	J结构定义 map[string]*J结构定义
	X详情   string
	C创建时间 *gtime.Time
	// 节点执行顺序
	Z执行队列  []string
	Z执行器映射 map[string]string
	// 是否开启事务
	S事务开关 *bool
}

type J结构定义 struct {
	B必填字段 []string `json:"MUST,omitempty"`
	J拒绝字段 []string `json:"REFUSE,omitempty"`
	W唯一字段 []string `json:"UNIQUE,omitempty"`

	// 不存在时添加
	C插入字段 g.Map `json:"INSERT,omitempty"`
	// 不存在时就添加，存在时就修改
	G更新字段 g.Map `json:"UPDATE,omitempty"`
	// 存在时替换
	T替换字段 g.Map `json:"REPLACE,omitempty"`
	// 存在时移除
	Y移除字段 []string `json:"REMOVE,omitempty"`
}

type Q请求配置集合 struct {
	Q请求映射表 map[string]*Q请求配置
}

func X新建请求配置集合(配置列表 []Q请求配置) *Q请求配置集合 {
	集合 := Q请求配置集合{}
	映射表 := make(map[string]*Q请求配置)

	for _, 配置项 := range 配置列表 {
		当前配置 := 配置项

		if 当前配置.J结构定义 == nil {
			当前配置.J结构定义 = make(map[string]*J结构定义)
		}

		if len(当前配置.Z执行队列) == 0 {
			标签名, _ := J解析标签(当前配置.B标签)
			当前配置.Z执行队列 = []string{标签名}
		}

		完整键 := S生成完整键(当前配置.B标签, 当前配置.Q请求方法, gconv.String(当前配置.B版本号))
		映射表[完整键] = &当前配置
		// 获取时按版本排序，所以此处最后一个为最新
		映射表[S生成完整键(当前配置.B标签, 当前配置.Q请求方法, "latest")] = &当前配置
	}

	集合.Q请求映射表 = 映射表
	return &集合
}

func S生成完整键(标签 string, 方法 string, 版本 string) string {
	return 标签 + "@" + 方法 + "@" + 版本
}

func (集合 *Q请求配置集合) H获取请求配置(标签 string, 方法 string, 版本 string) (*Q请求配置, error) {
	if 版本 == "" || 版本 == "-1" || 版本 == "0" {
		版本 = "latest"
	}

	键 := S生成完整键(标签, 方法, 版本)
	配置, 存在 := 集合.Q请求映射表[键]

	if !存在 {
		return nil, consts.X新建请求未找到错误(键)
	}

	return 配置, nil
}

func J解析标签(标签 string) (名称 string, 是否列表 bool) {
	if strings.HasSuffix(标签, consts.L列表键后缀) {
		名称 = 标签[0 : len(标签)-2]
		是否列表 = true
	} else {
		名称 = 标签
	}

	return
}
